-----------------------本地的cmd请求

local filename = "nodecmd.lua"

local skynet = require "skynet"
local cluster = require "skynet.cluster"
require "skynet.manager"

local configdao = require "configdao"
local timetool = require "timetool"
local filelog = require "filelog"
local tabletool = require "tabletool"

require "mjexenum"

local CMD = {}
local service = nil

function CMD.init(caller)
	service = caller -- 这里的caller，是router
end

function CMD.cmd(msg,...)
    if not msg then return end
    local f = CMD[msg]
    if not f then
        return
    end

    return f(...)
end

-----------------------------------------------

--
-- 删除桌子
-- 由游戏节点发来
--
function CMD.delete_table(table_index)
    filelog.print("------------delete table",table_index)
    if not table_index then
        return
    end

    table_index = tonumber(table_index) or 0
    local item = service.index_to_table[table_index]

    --删除大厅节点的code--index映射
    if item then
        local status,result = skynet.pcall(cluster.send,"hallnode", ".router","del_table_code",item.code,skynet.getenv("nodename"), table_index)
        service.code_to_index[item.code] = nil
    end
    service.index_to_table[table_index] = nil
    service.practice_table.idle_table[table_index] = nil
    service.practice_table.full_table[table_index] = nil
end

--
--离桌
--
function CMD.leave_table(rid,table_index,diamond)
    service:unforward(rid,table_index,diamond)
end

--
--进桌
--
function CMD.notice_gate_entertable(rid,table_service,table_index,diamond)
    service:forward(rid,table_service,table_index,diamond)
end

--
--获得桌子所有玩家rid
--
function CMD.gettableallrid(table_index)
    if table_index == nil then
        return {}
    end

    local rids = nil
    local item = service.index_to_table[table_index]
    if item then
        rids = skynet.call(item.table_service,"lua","cmd","get_table_allrid")
    end

    return {rids = rids}
end

--
--获得游戏状态：游戏中人数，等待人数，总人数，桌子数
--（不包括练习场）
--
function CMD.getgamestate()
    --自建钻石场信息
    local zijian_zuanshi_msg = { 
        total_player = 0,       --总玩家数
        table_num = 0,          --桌子数量
        ingame_player = 0,      --游戏中玩家数
        wait_player = 0,        --等待开始玩家数
    }

    --自建金币场信息
    local zijian_coin_msg = { 
        total_player = 0,       --总玩家数
        table_num = 0,          --桌子数量
        ingame_player = 0,      --游戏中玩家数
        wait_player = 0,        --等待开始玩家数
    }

    --练习场信息
    local lianxi_msg = {
        total_player = 0,       --总人数，不包括机器人
        table_num = 0,          --桌子数量,包括空闲桌子
    }

    local matchnum = 6
    --金豆匹配场信息
    local match_zuansi_msg = { }
    --金豆匹配场信息
    local match_coin_msg = { }
    for i = 1,matchnum  do
        match_zuansi_msg[i] = {
            total_player = 0,       --总玩家数
            table_num = 0,          --桌子数量
            ingame_player = 0,      --游戏中玩家数
            wait_player = 0,        --等待开始玩家数
        }
        match_coin_msg[i] = {
            total_player = 0,       --总玩家数
            table_num = 0,          --桌子数量
            ingame_player = 0,      --游戏中玩家数
            wait_player = 0,        --等待开始玩家数
        }
    end

    --房卡场信息
    local fangka_msg = {
        total_player = 0,       --总玩家数
        table_num = 0,          --桌子数量
        ingame_player = 0,      --游戏中玩家数
        wait_player = 0,        --等待开始玩家数
    }

    --总信息
    local total_msg = {
        total_player = 0,       --总玩家数
        table_num = 0,          --总桌子数量（包含空闲练习桌，空闲匹配桌，待删空桌子）
        ingame_player = 0,      --游戏中玩家数
        wait_player = 0,        --等待开始玩家数
    }

    for index,item in pairs(service.index_to_table) do
        local status,data = skynet.pcall(skynet.call,item.table_service,"lua","cmd","gettablestate")
        if status and data then
            local msg = nil
            if data.table_type == EMJTableType.TABLE_TYPE_ZIJIAN_ZUANSHI then       --匹配钻石场
                msg = zijian_zuanshi_msg
                if data.match_type then
                    msg = match_zuansi_msg[data.match_type]
                end
            elseif data.table_type == EMJTableType.TABLE_TYPE_ZIJIAN_FANGKA then    --房卡场
                msg = fangka_msg
            elseif data.table_type == EMJTableType.TABLE_TYPE_LIAN_XI_CHANG then    --练习场
                msg = lianxi_msg
            elseif data.table_type == EMJTableType.TABLE_TYPE_JIN_BI_CHANG then    --金豆场
                msg = zijian_coin_msg
                if data.match_type then
                    msg = match_coin_msg[data.match_type]
                end
            end

            if msg then
                if data.table_type ~= EMJTableType.TABLE_TYPE_LIAN_XI_CHANG then
                    msg.total_player = msg.total_player + data.cur_player_num
                    msg.table_num = msg.table_num + 1
                    if data.is_ingame then
                        msg.ingame_player = msg.ingame_player + data.cur_player_num
                    else
                        msg.wait_player = msg.wait_player + data.cur_player_num
                    end
                else
                    if service.practice_table.full_table[index] then
                        msg.total_player = msg.total_player + 1
                    end
                    msg.table_num = msg.table_num + 1
                end
            end
            
        end
    end

    local response = {
        zijian_diamond = zijian_zuanshi_msg.total_player,
        match_diamond = 0,
        zijian_coin = zijian_coin_msg.total_player,
        match_coin = 0,
        zijian_fangka = fangka_msg.total_player,
     }

    --统计总信息
    total_msg.total_player = zijian_coin_msg.total_player + zijian_zuanshi_msg.total_player + fangka_msg.total_player + lianxi_msg.total_player
    total_msg.table_num = zijian_zuanshi_msg.table_num + zijian_coin_msg.table_num + fangka_msg.table_num + lianxi_msg.table_num
    total_msg.ingame_player = zijian_coin_msg.ingame_player + zijian_zuanshi_msg.ingame_player + fangka_msg.ingame_player
    total_msg.wait_player = zijian_zuanshi_msg.wait_player + zijian_coin_msg.wait_player + fangka_msg.wait_player
    for k,item in pairs(match_zuansi_msg) do
        total_msg.total_player = total_msg.total_player + item.total_player
        total_msg.table_num = total_msg.table_num + item.table_num
        total_msg.ingame_player = total_msg.ingame_player + item.ingame_player
        total_msg.wait_player = total_msg.wait_player + item.wait_player
        response.match_diamond = response.match_diamond + item.total_player
    end
    for k,item in pairs(match_coin_msg) do
        total_msg.total_player = total_msg.total_player + item.total_player
        total_msg.table_num = total_msg.table_num + item.table_num
        total_msg.ingame_player = total_msg.ingame_player + item.ingame_player
        total_msg.wait_player = total_msg.wait_player + item.wait_player
        response.match_coin = response.match_coin + item.total_player
    end

    --获得匹配队列人数
    local match_num = service.CMD.match("get_matchqueue_len")
    local coinmatch_num = service.CMD.coinmatch("get_matchqueue_len")
    response.match_diamond = response.match_diamond + match_num
    response.match_coin = response.match_coin + coinmatch_num

    return response
end

--
--强制删除桌子
--
function CMD.destroytable(table_code, table_index)
    local responsemsg = { }
    local index = service.code_to_index[table_code] 
    if not index or not service.index_to_table[index] then
        responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
        responsemsg.retstr = "桌子不存在！"
        return responsemsg
    end

    local svr = service.index_to_table[index].table_service
    skynet.send(svr,"lua","cmd","delete",EMJTableDeleteReason.DELETE_REASON_SYSTEM_REQUIRE)

    return responsemsg
end

--
--获得桌子状态
--
function CMD.gettablestate(table_code)
    local responsemsg = { }
    local index = service.code_to_index[table_code] 
    if not index or not service.index_to_table[index] then
        responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
        responsemsg.retstr = "桌子不存在！"
        return responsemsg
    end

    local svr = service.index_to_table[index].table_service
    local msg = skynet.call(svr,"lua","cmd","gettablestate")

    return msg
end

--
--检测游戏状态,心跳超时的桌子将被删除
--只处理钻石场
--
function CMD.checkgamestate()
    local outtime = 60      --心跳超时60s
    local cur_time = timetool.get_time()

    --检测所有桌子
    for index,item in pairs(service.index_to_table) do
        local status,tableinfo = skynet.pcall(skynet.call,item.table_service,"lua","cmd","gettablestate")
        if status and tableinfo then
            if tableinfo.table_type == EMJTableType.TABLE_TYPE_ZIJIAN_ZUANSHI then
                local last_heart_time = tableinfo.last_heart_time or 0
                local cur_player_num = tableinfo.cur_player_num or 0
                local is_deleteing = tableinfo.is_deleteing or false
                local is_can_delete = false
                local is_delete_by_timer = true

                if tableinfo.is_ingame then
                    if cur_time - last_heart_time > outtime then
                        is_can_delete = true
                        is_delete_by_timer = false
                    end
                else
                    if cur_player_num <= 0 then
                         is_can_delete = true
                    elseif  tableinfo.table_state == EMJTableState.TABLE_STATE_WAIT_ALL_READY then
                        if cur_player_num - tableinfo.watch_player_num <= 0 then
                            is_can_delete = true
                        elseif cur_time - last_heart_time > outtime * 30 then
                            is_can_delete = true
                            is_delete_by_timer = true
                        end
                    end
                end 
                if is_can_delete and not is_deleteing then
                    if is_delete_by_timer then
                        skynet.send(item.table_service,"lua","cmd","delete_table_by_timer")
                    else
                        skynet.send(item.table_service,"lua","cmd","delete",EMJTableDeleteReason.DELETE_REASON_SYSTEM_ERROR)
                    end
                end
            elseif tableinfo.table_type == EMJTableType.TABLE_TYPE_LIAN_XI_CHANG then
                if tableinfo.cur_player_num < tableinfo.max_player_num then
                    if not service.practice_table.idle_table[index] then
                        service.practice_table.full_table[index] = nil
                        service.practice_table.idle_table[index] = index
                    end
                end
            end
        end
    end  
end

--
--创建练习场
--
function CMD.create_practice_table(table_conf)
    if not table_conf then
        table_conf = {
            table_type = EMJTableType.TABLE_TYPE_LIAN_XI_CHANG,
            max_player_num = 4,
            is_public = 0,
            score_diamond = 100,
            enter_diamond = 3000,
            leave_diamond = 1500,
        }
    end

    local roledata = {
        info = { 
            rolename = "root",  --名字
            level = 0,          --等级
		    logo = "",          --头像
		    sex = 1,            --性别
            rid = 111111111,
        },
        money = {
            diamond = 99999999,
            fangka = 9999999,
            coin = 99999999,
            dou = 99999999,
            lock_diamond = 0,
         },
        table_persist = 3600,   --保留1个小时
        ip_addr = "",
    }

    local func = service.CMD.createtable
    local msgbody = {table_conf = table_conf}

    return func(roledata.info.rid,roledata,msgbody)
end

--
--创建一些练习桌
--tablenum 创建数量
--
function CMD.create_some_practice_table(tablenum)
    tablenum = (tablenum or 1) * 2
    if tablenum <= 0 then
        return
    end

    local idle_practice_table = service.practice_table.idle_table
    for i = 1,tablenum do
        local new_table = service.CMD.create_practice_table()
        if new_table and new_table.table_index then
            idle_practice_table[new_table.table_index] = new_table.table_index
        end
    end
end


--
--获得游戏节点数据
--
function CMD.get_gamenode_data()
    local codelist = { }

    --获得桌子列表
    for index,item in pairs(service.index_to_table) do
        local status,data = skynet.pcall(skynet.call,item.table_service,"lua","cmd","get_table_data")
        if status and data then
            if data.table_type ~= EMJTableType.TABLE_TYPE_LIAN_XI_CHANG then
                codelist[data.table_code] = {
                    table_index = data.table_index,
                    create_rid = data.create_rid,
                    conf = tabletool.deepcopy(data.conf),
                    create_time = data.create_time,
                }
            end
        end
    end

    return codelist
end

--
--将桌子加入空闲练习桌列表
--
function CMD.add_to_idle_practice_table(table_index)
    service.practice_table.full_table[table_index] = nil
    if service.index_to_table[table_index] then
        service.practice_table.idle_table[table_index] = table_index
    else
        service.practice_table.idle_table[table_index] = nil
    end
end

--
--设置桌子结束标记
--
function CMD.set_tableend_flag(table_code)
    if not table_code or not service.code_to_index[table_code] then
        return false
    end

    local is_ok = false 
    local table_index = service.code_to_index[table_code]
    local item = service.index_to_table[table_index]
    if item and item.table_service then 
        skynet.send(item.table_service,"lua","cmd","set_tableend_flag")
    end
end

--
--设置游戏服结束标记
--
function CMD.set_gameend_flag()
    service.gameend_flag = true

    --删掉所有等待桌,并给游戏中桌子设置结束标记
    for index,item in pairs(service.index_to_table) do
        local status,tableinfo = skynet.pcall(skynet.call,item.table_service,"lua","cmd","gettablestate")
        if status and tableinfo and not tableinfo.is_deleteing then
            if tableinfo.table_state == EMJTableState.TABLE_STATE_WAIT_PLAYER_SITDOWN
            or tableinfo.table_state == EMJTableState.TABLE_STATE_WAIT_ALL_READY then
                skynet.send(item.table_service,"lua","cmd","delete",EMJTableDeleteReason.DELETE_REASON_SYSTEM_ERROR)
            else
                skynet.send(item.table_service,"lua","cmd","set_tableend_flag")
            end
        end
    end
end

--
--清除玩家状态
--
function CMD.clear_player_state(rid)
    if not rid or rid <= 0 then
        return
    end

    if service.role_map[rid] then
        service.role_map[rid] = nil
    end
end

--
--获取桌子数据
--
function CMD.get_tableinfo(table_index, rid)
    if not table_index or not service.index_to_table[table_index] then
        return { retcode = EErrCode.ERR_INVALID_REQUEST, retstr = "桌子不存在！"}
    end
    local svr = service.index_to_table[table_index].table_service
    return skynet.call(svr, "lua", "cmd", "get_tableinfo", rid)
end

--
--获取所有桌子数据
--
function CMD.get_alltableinfo()
    local all_tableinfo = {
        tableinfos = {},
    }
    for index,item in pairs(service.index_to_table) do
        local status,data = skynet.pcall(skynet.call,item.table_service,"lua","cmd","get_tableinfo")
        if status and data then
            table.insert(all_tableinfo.tableinfos,data)
        end
    end

    --获得匹配场信息
    all_tableinfo.match_infos = service.CMD.match("get_matchinfo")
    all_tableinfo.coinmatch_infos = service.CMD.coinmatch("get_matchinfo")

    return all_tableinfo
end

--
--机器人建桌
--
function CMD.robot_createtable(conf)
    local roledata = conf.roledata
    local table_conf = conf.table_conf

    if not roledata then
        roledata = {
            info = { 
                rolename = "robot", --名字
                level = 99,         --等级
		        logo = "1",         --头像
		        sex = 2,            --性别
                rid = 33333333,
            },
            money = {
                diamond = 99999999,
                fangka = 9999999,
                coin = 99999999,
                dou = 99999999,
                lock_diamond = 0,
             },
            ip_addr = "",
        }
    end

    local func = service.CMD.createtable
    local msgbody = {table_conf = table_conf}

    return func(roledata.info.rid,roledata,msgbody)
end

return CMD